home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9207.ZIP / ACOMP.ZIP / UNC.C < prev    next >
C/C++ Source or Header  |  1992-04-14  |  7KB  |  191 lines

  1. #include "uc.h"
  2.  
  3. /*****************************************************************************/
  4. /* UNC.C     This is the C version of the ACOMP decompressor.  Compare it to     */
  5. /*                 the assembly language version of the same, in UC.ASM.    The              */
  6. /*                 assembly version of the decompressor is 2.4 times faster than the */
  7. /*                 C version.  Probabably some hand optimization of either would         */
  8. /*                 change these statistics.                                                                                  */
  9. /*                 It is very imporant to note that you could deburst this algorithm */
  10. /*                 so that it could decompress portions of the audio, as a background*/
  11. /*                 task, thus allowing you to play back and decompress digitized         */
  12. /*                 sound, simultaneously!  This would allow you to play back large     */
  13. /*                 digitized sound samples while using a very limited amount of core */
  14. /*                 memory.    The UCOMP decompressor could easily be put into a              */
  15. /*                 hardware based system, and it's performance characteristics far   */
  16. /*                 exceed current hardware based audio decompression systems such as */
  17. /*                 CVSD and LPC encoding.                                                                                      */
  18. /*                 To give you some performance characteristics look at the following*/
  19. /*                 On my 20mhz 386 system, it took 0.1141 seconds to decompress 58k  */
  20. /*                 of audio. (0.3451 seconds using the C version.) That comes              */
  21. /*                 out to 600k per second!    The amount of CPU overhead to                      */
  22. /*                 decompress the audio, as it is played back, is truely                         */
  23. /*                 negligible.                                                                                                             */
  24. /*****************************************************************************/
  25.  
  26. #define SQLCH 0x40        // Squelch byte flag
  27. #define RESYNC 0x80     // Resync byte flag.
  28.  
  29. #define DELTAMOD 0x30     // Delta modulation bits.
  30.  
  31. #define ONEBIT 0x10         // One bit delta modulate
  32. #define TWOBIT 0x20         // Two bit delta modulate
  33. #define FOURBIT 0x30        // four bit delta modulate
  34.  
  35. #define MULTIPLIER 0x0F  // Bottom nibble contains multiplier value.
  36. #define SQUELCHCNT 0x3F  // Bits for squelching.
  37.  
  38. static signed char trans[16*16] =
  39. {
  40.     -8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8,                                            // Multiplier of 1
  41.     -16,-14,-12,-10,-8,-6,-4,-2,2,4,6,8,10,12,14,16,                            // Multiplier of 2
  42.     -24,-21,-18,-15,-12,-9,-6,-3,3,6,9,12,15,18,21,24,                        // Multiplier of 3
  43.     -32,-28,-24,-20,-16,-12,-8,-4,4,8,12,16,20,24,28,32,                    // Multiplier of 4
  44.     -40,-35,-30,-25,-20,-15,-10,-5,5,10,15,20,25,30,35,40,                // Multiplier of 5
  45.     -48,-42,-36,-30,-24,-18,-12,-6,6,12,18,24,30,36,42,48,                // Multiplier of 6
  46.     -56,-49,-42,-35,-28,-21,-14,-7,7,14,21,28,35,42,49,56,                // Multiplier of 7
  47.     -64,-56,-48,-40,-32,-24,-16,-8,8,16,24,32,40,48,56,64,                // Multiplier of 8
  48.     -72,-63,-54,-45,-36,-27,-18,-9,9,18,27,36,45,54,63,72,                // Multiplier of 9
  49.     -80,-70,-60,-50,-40,-30,-20,-10,10,20,30,40,50,60,70,80,            // Multiplier of 10
  50.     -88,-77,-66,-55,-44,-33,-22,-11,11,22,33,44,55,66,77,88,            // Multiplier of 11
  51.     -96,-84,-72,-60,-48,-36,-24,-12,12,24,36,48,60,72,84,96,            // Multiplier of 12
  52.     -104,-91,-78,-65,-52,-39,-26,-13,13,26,39,52,65,78,91,104,        // Multiplier of 13
  53.     -112,-98,-84,-70,-56,-42,-28,-14,14,28,42,56,70,84,98,112,        // Multiplier of 14
  54.     -120,-105,-90,-75,-60,-45,-30,-15,15,30,45,60,75,90,105,120,    // Multiplier of 15
  55.     -127,-112,-96,-80,-64,-48,-32,-16,16,32,48,64,80,96,112,127 };    // Multiplier of 16
  56.  
  57. short Get8086word(unsigned char far *temp);
  58.  
  59. // UnCompressAudio will decompress data which was compressed using ACOMP
  60. // into the destination address provided.  UnCompressAudio returns the
  61. // total size, in bytes, of the uncompressed audio data.
  62. unsigned int    far UnCompressAudio(unsigned char far *source,unsigned char far *dest)
  63. {
  64.     unsigned short slen,frame,bits,count,length,plier,bytes;
  65.     unsigned char sample,mask;
  66.     short prev,up,down,one,two,three,four;
  67.     signed char *base;
  68.  
  69.     slen = length = Get8086word(source);
  70.     source+=4;                    // Skip length, and then frequency word.
  71.     frame = *source++;    // Frame size.
  72.     source+=3;                     // Skip sqelch value, and maximum error allowed.
  73.     prev = *dest++ = *source++;      // Get initial previous data point.
  74.     slen--;                          // Decrement total sound length.
  75.     while ( slen )    // While still audio data to decompress....
  76.     {
  77.         sample = *source++;  // Get sample.
  78.         if ( sample & RESYNC ) // Is it a resync byte?
  79.         {
  80.             *dest++ = prev = (sample&0x7F)<<1; // Store resync byte.
  81.             slen--;  // Decrement output sample length.
  82.         }
  83.         else
  84.         {
  85.             if ( sample & SQLCH ) // Is it a squelch byte?
  86.             {
  87.                 count = sample&SQUELCHCNT;    // And off the number of squelch bytes
  88.                 slen-=count;    // Decrement total samples remaining count.
  89.                 for (; count; count--) *dest++ = prev; // send the repeated data out..
  90.             }
  91.             else        // Must be a delta modulate byte!!
  92.             {
  93.                 bits = sample&DELTAMOD; // Delta mod resolution.
  94.                 plier = sample&MULTIPLIER;
  95.                 base = trans+plier*16;    // Compute base address to multiplier table.
  96.                 slen-=frame; // Pulling one frame out.
  97.                 switch ( bits )
  98.                 {
  99.                     case ONEBIT:
  100.                                     bytes = frame/8; // 8 samples per byte.
  101.                                     down = base[7]; // Go down 1 bit.
  102.                                     up = base[8];     // Go up 1 bit.
  103.                                     for (;bytes;bytes--)
  104.                                     {
  105.                                         sample = *source++;
  106.                                         for(mask=0x80; mask; mask=mask>>1)
  107.                                         {
  108.                                             if ( sample & mask )
  109.                                                 prev+=up;
  110.                                             else
  111.                                                 prev+=down;
  112.                                             if ( prev < 0 ) prev = 0;
  113.                                             if ( prev > 255 ) prev = 255;
  114.                                             *dest++=prev;
  115.                                         }
  116.                                     }
  117.                                     break;
  118.                     case TWOBIT:
  119.                                     bytes = frame/4;        // 4 samples per byte.
  120.                                     base+=6; // Base address of two bit delta's.
  121.                                     for (;bytes;bytes--)
  122.                                     {
  123.                                         sample = *source++;
  124.                                         one = sample>>6; // Top two bits.
  125.                                         two = (sample>>4)&0x3; // Next two bits.
  126.                                         three = (sample>>2)&0x3; // New two.
  127.                                         four = sample&0x3; // last two.
  128.  
  129.                                         prev+=base[one];
  130.                                         if ( prev < 0 ) prev = 0;
  131.                                         if ( prev > 255 ) prev = 255;
  132.                                         *dest++=prev;
  133.  
  134.                                         prev+=base[two];
  135.                                         if ( prev < 0 ) prev = 0;
  136.                                         if ( prev > 255 ) prev = 255;
  137.                                         *dest++=prev;
  138.  
  139.                                         prev+=base[three];
  140.                                         if ( prev < 0 ) prev = 0;
  141.                                         if ( prev > 255 ) prev = 255;
  142.                                         *dest++=prev;
  143.  
  144.                                         prev+=base[four];
  145.                                         if ( prev < 0 ) prev = 0;
  146.                                         if ( prev > 255 ) prev = 255;
  147.                                         *dest++=prev;
  148.                                     }
  149.                                     break;
  150.                     case FOURBIT:
  151.                                     bytes = frame/2;
  152.                                     for (;bytes;bytes--)
  153.                                     {
  154.                                         sample = *source++;
  155.                                         up = sample>>4; // High nibble.
  156.                                         down = sample&0x0F; // Low nibble.
  157.                                         prev+=base[up];
  158.                                         if ( prev < 0 ) prev = 0;
  159.                                         if ( prev > 255 ) prev = 255;
  160.                                         *dest++=prev;
  161.                                         prev+=base[down];
  162.                                         if ( prev < 0 ) prev = 0;
  163.                                         if ( prev > 255 ) prev = 255;
  164.                                         *dest++=prev;
  165.                                     }
  166.                                     break;
  167.                 }
  168.             }
  169.         }
  170.     }
  171.     return( length );
  172. }
  173.  
  174. // GetFreq will report the playback frequency of a particular ACOMP data
  175. // file.
  176. unsigned int    far GetFreq(unsigned char far *sound)
  177. {
  178.     return( Get8086word(sound+2) );
  179. }
  180.  
  181. // This is used to make certain this C code is compatible when compiled on
  182. // a 68000 based machine.  (Which it has been done and tested on.)
  183. short Get8086word(unsigned char far *temp)
  184. {
  185.     short low,high;
  186.  
  187.     low = *temp++;
  188.     high = *temp;
  189.     return( low + high*256 );
  190. }
  191.